package mornd.test5;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author: mornd
 * @dateTime: 2023/5/6 - 22:50
 * 手写一个调用链（责任链模式）
 */
public class Demo {

    public static void main(String[] args) throws Throwable {
        // 声明通知执行链
        List<MethodInterceptor> list = new ArrayList<>();
        list.add(new Advice1());
        list.add(new Advice2());

        // 目标对象
        Target target = new Target();

        // 声明责任链的调用者
        MyInvocation foo =
                new MyInvocation(target, Target.class.getDeclaredMethod("foo"), new Object[0], list);

        Object proceed = foo.proceed();
        System.out.println(proceed);
    }

    static class Target {
        public void foo() {
            System.out.println("target foo");
        }
    }

    static class MyInvocation implements MethodInvocation {
        // 目标对象
        private Object target;
        // 目标方法
        private Method method;
        // 目标方法参数
        private Object[] args;
        // 通知链
        List<MethodInterceptor> methodInterceptors;

        private static int count = 0;

        public MyInvocation(Object target, Method method, Object[] args, List<MethodInterceptor> methodInterceptors) {
            this.target = target;
            this.method = method;
            this.args = args;
            this.methodInterceptors = methodInterceptors;
        }

        @Override
        public Method getMethod() {
            return method;
        }

        @Override
        public Object[] getArguments() {
            return args;
        }

        @Override
        public Object proceed() throws Throwable {
            if(count++ >= methodInterceptors.size()) {
                return method.invoke(target, args);
            } else {
                return methodInterceptors.get(count - 1).invoke(this);
            }

//            Iterator<MethodInterceptor> iterator = methodInterceptors.iterator();
//            while (iterator.hasNext()) {
//                MethodInterceptor next = iterator.next();
//                iterator.remove();
//                return next.invoke(this);
//            }
//            return method.invoke(target, args);
        }

        @Override
        public Object getThis() {
            return target;
        }

        @Override
        public AccessibleObject getStaticPart() {
            return method;
        }
    }

    static class Advice1 implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice1 before...");
            Object result = invocation.proceed(); // 调用下一个通知或目标
            System.out.println("Advice1 after...");
            return result;
        }
    }

    static class Advice2 implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice2 before...");
            Object result = invocation.proceed(); // 调用下一个通知或目标
            System.out.println("Advice2 after...");
            return result;
        }
    }
}
